<template>
  <div ref="view" :style="{height: height, width: '100%'}"/>
</template>

<script>
import { Graph, Path } from '@antv/x6'
import Hierarchy from '@antv/hierarchy'

const globalNetwork = {
  2: { name: 'networkTwo', width: 200, height: 32 },
  3: { name: 'networkThree', width: 200, height: 58 },
  4: { name: 'networkFour', width: 200, height: 75 }
}

export default {
  name: 'NetworkChart',
  props: {
    data: {
      type: Object,
      default: function() {
        return null
      }
    },
    height: {
      type: String,
      default: '500px'
    }
  },
  data() {
    return {
      nodeType: this.$store.state.fmea.nodeType,
      graph: null,
      networkThree: {
        width: 200,
        height: 60
      }
    }
  },
  watch: {
    data: {
      handler() {
        this.importData()
      },
      deep: true
    }
  },
  mounted() {
    this.registry()
    this.importData()
  },
  methods: {
    // 导入数据
    importData() {
      if (this.data) {
        if (this.graph === null) {
          this.graph = new Graph(
            {
              container: this.$refs.view,
              panning: true,
              connecting: {
                connectionPoint: 'anchor'
              },
              selecting: {
                enabled: true
              },
              keyboard: {
                enabled: true
              }
            }
          )
        }

        const render = () => {
          const cells = []
          const traverse = (hierarchyItem) => {
            if (hierarchyItem) {
              const { children } = hierarchyItem
              cells.push(
                this.createNode(hierarchyItem)
              )
              if (children) {
                children.forEach((item) => {
                  const { id, side } = item
                  cells.push(this.createEdge(id, hierarchyItem.id, side))
                  traverse(item)
                })
              }
            }
          }
          traverse(this.formatData(this.data))
          this.graph.resetCells(cells)
          this.graph.centerContent()
        }
        render()
      } else {
        // 清空视图
        if (this.graph) {
          this.graph.dispose()
          this.graph = null
        }
      }
    },
    // 格式化数据
    formatData(data) {
      let idMap = 0
      return Hierarchy.mindmap(data, {
        direction: 'H',
        getId() {
          return ++idMap
        },
        getHeight(d) {
          return globalNetwork[d.data.length].height
        },
        getWidth(d) {
          return globalNetwork[d.data.length].width
        },
        getHGap() {
          return 20
        },
        getVGap() {
          return 5
        },
        getSide: (d) => {
          return d.data.direction
        }
      })
    },
    // 创建节点
    createNode(hierarchyItem) {
      const { data } = hierarchyItem

      const node = {
        id: hierarchyItem.id,
        x: hierarchyItem.x,
        y: hierarchyItem.y,
        width: globalNetwork[data.data.length].width,
        height: globalNetwork[data.data.length].height,
        attrs: {
          title: {
            text: data.data.map(item => item.text).join('\n')
          }
        },
        color: 'red'
      }
      const names = ['label', 'labelOne', 'labelTwo', 'labelThree']
      data.data.forEach((item, index) => {
        node.attrs[names[index]] = {
          text: item.text,
          fill: this.getColor(item.nodeType)
        }
      })
      node.shape = globalNetwork[data.data.length].name
      return this.graph.createNode(node)
    },
    // 创建边
    createEdge(sourceId, targetId, type) {
      return this.graph.createEdge({
        shape: 'mindmap-edge',
        source: {
          cell: sourceId,
          anchor: type === 'right' ? { name: 'left' } : { name: 'right' }
        },
        target: {
          cell: targetId,
          anchor: { name: type }
        }
      })
    },
    // 获取节点颜色
    getColor(value) {
      let color
      switch (value) {
        case this.nodeType.function.value:
          color = this.nodeType.function.color
          break
        case this.nodeType.character.value:
          color = this.nodeType.character.color
          break
        case this.nodeType.failure.value:
          color = this.nodeType.failure.color
          break
        case this.nodeType.failureEffect.value:
          color = this.nodeType.failureEffect.color
          break
        case this.nodeType.failureMode.value:
          color = this.nodeType.failureMode.color
          break
        case this.nodeType.failureReason.value:
          color = this.nodeType.failureReason.color
          break
        default:
          color = '#000'
      }
      return color
    },
    // 注册自定义节点、边
    registry() {
      // 节点三
      Graph.registerNode(
        'networkTwo',
        {
          inherit: 'rect',
          markup: [
            {
              tagName: 'rect',
              selector: 'body'
            },
            {
              tagName: 'title',
              selector: 'title'
            },
            {
              tagName: 'text',
              selector: 'label'
            }, {
              tagName: 'text',
              selector: 'labelOne'
            }
          ],
          attrs: {
            body: {
              rx: 6,
              ry: 6,
              stroke: '#5F95FF',
              fill: '#FFF',
              strokeWidth: 1
            },
            label: {
              textWrap: {
                ellipsis: true,
                height: '50%',
                width: -25
              },
              refX: 5,
              refY: 12,
              fontSize: 12,
              fill: '#262626',
              'text-anchor': 'start'
            },
            labelOne: {
              textWrap: {
                ellipsis: true,
                height: '50%',
                width: -25
              },
              refX: 5,
              refY: 29,
              fontSize: 12,
              fill: '#262626',
              'text-anchor': 'start'
            }
          }
        },
        true
      )

      // 节点三
      Graph.registerNode(
        'networkThree',
        {
          inherit: 'rect',
          markup: [
            {
              tagName: 'rect',
              selector: 'body'
            },
            {
              tagName: 'title',
              selector: 'title'
            },
            {
              tagName: 'text',
              selector: 'label'
            }, {
              tagName: 'text',
              selector: 'labelOne'
            },
            {
              tagName: 'text',
              selector: 'labelTwo'
            }
          ],
          attrs: {
            body: {
              rx: 6,
              ry: 6,
              stroke: '#5F95FF',
              fill: '#FFF',
              strokeWidth: 1
            },
            label: {
              textWrap: {
                ellipsis: true,
                height: '33%',
                width: -25
              },
              refX: 5,
              refY: 12,
              fontSize: 12,
              fill: '#262626',
              'text-anchor': 'start'
            },
            labelOne: {
              textWrap: {
                ellipsis: true,
                height: '33%',
                width: -25
              },
              refX: 5,
              refY: 29,
              fontSize: 12,
              fill: '#262626',
              'text-anchor': 'start'
            },
            labelTwo: {
              textWrap: {
                ellipsis: true,
                height: '33%',
                width: -25
              },
              refX: 5,
              refY: 46,
              fontSize: 12,
              fill: '#262626',
              'text-anchor': 'start'
            }
          }
        },
        true
      )

      // 节点四
      Graph.registerNode(
        'networkFour',
        {
          inherit: 'rect',
          markup: [
            {
              tagName: 'rect',
              selector: 'body'
            },
            {
              tagName: 'title',
              selector: 'title'
            },
            {
              tagName: 'text',
              selector: 'label'
            }, {
              tagName: 'text',
              selector: 'labelOne'
            },
            {
              tagName: 'text',
              selector: 'labelTwo'
            },
            {
              tagName: 'text',
              selector: 'labelThree'
            }
          ],
          attrs: {
            body: {
              rx: 6,
              ry: 6,
              stroke: '#5F95FF',
              fill: '#FFF',
              strokeWidth: 1
            },
            label: {
              textWrap: {
                ellipsis: true,
                height: '25%',
                width: -25
              },
              refX: 5,
              refY: 12,
              fontSize: 12,
              fill: '#262626',
              'text-anchor': 'start'
            },
            labelOne: {
              textWrap: {
                ellipsis: true,
                height: '25%',
                width: -25
              },
              refX: 5,
              refY: 29,
              fontSize: 12,
              fill: '#262626',
              'text-anchor': 'start'
            },
            labelTwo: {
              textWrap: {
                ellipsis: true,
                height: '25%',
                width: -25
              },
              refX: 5,
              refY: 46,
              fontSize: 12,
              fill: '#262626',
              'text-anchor': 'start'
            },
            labelThree: {
              textWrap: {
                ellipsis: true,
                height: '25%',
                width: -25
              },
              refX: 5,
              refY: 63,
              fontSize: 12,
              fill: '#262626',
              'text-anchor': 'start'
            }
          }
        },
        true
      )

      // 连接器
      Graph.registerConnector(
        'mindmap',
        (sourcePoint, targetPoint, routerPoints, options) => {
          const midX = sourcePoint.x + 10
          const midY = sourcePoint.y
          const ctrX = (targetPoint.x - midX) / 5 + midX
          const ctrY = targetPoint.y
          const pathData = `
     M ${sourcePoint.x} ${sourcePoint.y}
     L ${midX} ${midY}
     Q ${ctrX} ${ctrY} ${targetPoint.x} ${targetPoint.y}
    `
          return options.raw ? Path.parse(pathData) : pathData
        },
        true
      )

      // 边
      Graph.registerEdge(
        'mindmap-edge',
        {
          inherit: 'edge',
          attrs: {
            line: {
              targetMarker: '',
              stroke: '#A2B1C3',
              strokeWidth: 1
            }
          },
          zIndex: 0
        },
        true
      )
    }
  }
}
</script>
